package com.rfid.project.service;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Sort;
import org.springframework.data.domain.Sort.Direction;

import biz.util.*;

import com.rfid.project.model.*;
import com.rfid.project.dao.*;
import com.rfid.project.exception.CannotUpdateException;
import com.mysema.query.BooleanBuilder;

import java.util.Date;
import java.util.Calendar;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

@Service
@Transactional
public class ProjectMilestoneChangeService{

	@Autowired
	private ProjectMilestoneChangeDao projectMilestoneChangeDao;
	
	private QProjectMilestoneChange $ = QProjectMilestoneChange.projectMilestoneChange;
	
	@Autowired
	public void setProjectMilestoneChangeDao(ProjectMilestoneChangeDao projectMilestoneChangeDao) {
		this.projectMilestoneChangeDao = projectMilestoneChangeDao;
	}

	@Autowired
	private ProjectMilestoneDao projectMilestoneDao;

	private QProjectMilestone $_projectMilestone = QProjectMilestone.projectMilestone;

	@Autowired
	public void setProjectMilestoneDao(ProjectMilestoneDao projectMilestoneDao) {
		this.projectMilestoneDao = projectMilestoneDao;
	}
	
	public List<ProjectMilestoneChange> findAll(){
		return ListUtil.toList(projectMilestoneChangeDao.findAll());
	}

	@Autowired
	private ProjectStakeholderDao projectStakeholderDao;
	
	private QProjectStakeholder $_projectStakeholder = QProjectStakeholder.projectStakeholder;
	
	@Autowired
	public void setProjectStakeholderDao(ProjectStakeholderDao projectStakeholderDao) {
		this.projectStakeholderDao = projectStakeholderDao;
	}
				
	public List<ProjectMilestoneChange> findAll(
	Long projectMilestoneId,
	Date originalDateBegin,
	Date originalDateEnd,
	Date targetDateBegin,
	Date targetDateEnd,
	Long applyPersonId,
	Date applyTimeBegin,
	Date applyTimeEnd,
	String applyReason,
	Date checkTimeBegin,
	Date checkTimeEnd,
	Long checkPersonId,
	String checkComment,
	String status,
	String orderByAttribute	){
	BooleanBuilder condition = new BooleanBuilder();
	
	if(IdUtil.isNotEmpty(projectMilestoneId)){
		condition.and($.projectMilestone.id.eq(projectMilestoneId));
	}
	
	if(originalDateBegin != null){
		condition.and($.originalDate.after(originalDateBegin));
	}
	
	if(originalDateEnd != null){
		condition.and($.originalDate.before(originalDateEnd));
	}
	
	if(targetDateBegin != null){
		condition.and($.targetDate.after(targetDateBegin));
	}
	
	if(targetDateEnd != null){
		condition.and($.targetDate.before(targetDateEnd));
	}
	
	if(IdUtil.isNotEmpty(applyPersonId)){
		condition.and($.applyPerson.id.eq(applyPersonId));
	}
	
	if(applyTimeBegin != null){
		condition.and($.applyTime.after(applyTimeBegin));
	}
	
	if(applyTimeEnd != null){
		condition.and($.applyTime.before(applyTimeEnd));
	}
	
	if(StringUtil.isNotEmpty(applyReason)){
		condition.and($.applyReason.contains(applyReason));
	}
	
	if(checkTimeBegin != null){
		condition.and($.checkTime.after(checkTimeBegin));
	}
	
	if(checkTimeEnd != null){
		condition.and($.checkTime.before(checkTimeEnd));
	}
	
	if(IdUtil.isNotEmpty(checkPersonId)){
		condition.and($.checkPerson.id.eq(checkPersonId));
	}
	
	if(StringUtil.isNotEmpty(checkComment)){
		condition.and($.checkComment.contains(checkComment));
	}
	
	if(StringUtil.isNotEmpty(status)){
		condition.and($.status.contains(status));
	}
	
	
	return ListUtil.toList(projectMilestoneChangeDao.findAll(condition));
	}		

	public Page<ProjectMilestoneChange> findAll(
			Long projectMilestoneId,
			Date originalDateBegin,
			Date originalDateEnd,
			Date targetDateBegin,
			Date targetDateEnd,
			Long applyPersonId,
			Date applyTimeBegin,
			Date applyTimeEnd,
			String applyReason,
			Date checkTimeBegin,
			Date checkTimeEnd,
			Long checkPersonId,
			String checkComment,
			String status,
			int pageNumber, int pageSize,String sortAttribute,String orderDirection) {
			BooleanBuilder condition = new BooleanBuilder();
	
			if(IdUtil.isNotEmpty(projectMilestoneId)){
				condition.and($.projectMilestone.id.eq(projectMilestoneId));
			}
			if(originalDateBegin != null){
				condition.and($.originalDate.after(originalDateBegin));
			}
			
			if(originalDateEnd != null){
				condition.and($.originalDate.before(originalDateEnd));
			}
			if(targetDateBegin != null){
				condition.and($.targetDate.after(targetDateBegin));
			}
			
			if(targetDateEnd != null){
				condition.and($.targetDate.before(targetDateEnd));
			}
			if(IdUtil.isNotEmpty(applyPersonId)){
				condition.and($.applyPerson.id.eq(applyPersonId));
			}
			if(applyTimeBegin != null){
				condition.and($.applyTime.after(applyTimeBegin));
			}
			
			if(applyTimeEnd != null){
				condition.and($.applyTime.before(applyTimeEnd));
			}
			if(StringUtil.isNotEmpty(applyReason)){
				condition.and($.applyReason.contains(applyReason));
			}
			if(checkTimeBegin != null){
				condition.and($.checkTime.after(checkTimeBegin));
			}
			
			if(checkTimeEnd != null){
				condition.and($.checkTime.before(checkTimeEnd));
			}
			if(IdUtil.isNotEmpty(checkPersonId)){
				condition.and($.checkPerson.id.eq(checkPersonId));
			}
			if(StringUtil.isNotEmpty(checkComment)){
				condition.and($.checkComment.contains(checkComment));
			}
			if(StringUtil.isNotEmpty(status)){
				condition.and($.status.contains(status));
			}
	
			Sort sortObject = null;
			if(StringUtil.isEmpty(sortAttribute)){
				sortObject = new Sort(Direction.DESC, "id");
			}else{
				sortObject = new Sort(Direction.fromStringOrNull(orderDirection),sortAttribute);
			}
			
			PageRequest pageRequest = new PageRequest(pageNumber - 1, pageSize, sortObject);
			return projectMilestoneChangeDao.findAll(condition, pageRequest);
	}
	
	public ProjectMilestoneChange getProjectMilestoneChange(Long id){
		return projectMilestoneChangeDao.getOne(id);
	}
	
	public void deleteProjectMilestoneChange(Long id){
		projectMilestoneChangeDao.delete(id);
	}

	public void saveProjectMilestoneChange(ProjectMilestoneChange projectMilestoneChange) {
		if (null == projectMilestoneChange.getApplyTime()) {
			projectMilestoneChange.setApplyTime(Calendar.getInstance().getTime());
		}
		
		ProjectMilestone projectMilestone = this.projectMilestoneDao.findOne(projectMilestoneChange.getProjectMilestone().getId());
		projectMilestone.setStatus(projectMilestoneChange.getProjectMilestone().getStatus());
		
		this.projectMilestoneChangeDao.save(projectMilestoneChange);
		this.projectMilestoneDao.save(projectMilestone);
	}
	
	public Set<People> findApplyPersonsByProject(Project project){
		BooleanBuilder condition = new BooleanBuilder();
		condition.and($_projectMilestone.project.id.eq(project.getId()));
		List<ProjectMilestone> projectMiestones = ListUtil.toList(this.projectMilestoneDao.findAll(condition));
		Set<Long> right = new HashSet<Long>();
		for (ProjectMilestone projectMilestone : projectMiestones) {
			right.add(projectMilestone.getId());
		}
		condition = new BooleanBuilder();
		condition.and($.projectMilestone.id.in(right));
		List<ProjectMilestoneChange> projectMilestoneChanges = ListUtil.toList(this.projectMilestoneChangeDao.findAll(condition));
		Set<People> peoples = new HashSet<People>();
		for (ProjectMilestoneChange projectMilestoneChange : projectMilestoneChanges) {
			peoples.add(projectMilestoneChange.getApplyPerson());
		}
		return peoples;
	}

	public Set<People> findCheckPersonsByProject(Project project){
		BooleanBuilder condition = new BooleanBuilder();
		condition.and($_projectMilestone.project.id.eq(project.getId()));
		List<ProjectMilestone> projectMiestones = ListUtil.toList(this.projectMilestoneDao.findAll(condition));
		Set<Long> right = new HashSet<Long>();
		for (ProjectMilestone projectMilestone : projectMiestones) {
			right.add(projectMilestone.getId());
		}
		condition = new BooleanBuilder();
		condition.and($.projectMilestone.id.in(right));
		List<ProjectMilestoneChange> projectMilestoneChanges = ListUtil.toList(this.projectMilestoneChangeDao.findAll(condition));
		Set<People> peoples = new HashSet<People>();
		for (ProjectMilestoneChange projectMilestoneChange : projectMilestoneChanges) {
			peoples.add(projectMilestoneChange.getCheckPerson());
		}
		return peoples;
	}

	public List<ProjectMilestoneChange> findByStatus(People people, Long projectStakeholderType, String status) {
		BooleanBuilder condition = new BooleanBuilder();
		condition.and(this.$_projectStakeholder.personID.eq(people.getId()));
		condition.and(this.$_projectStakeholder.projectStakeholderType.id.eq(projectStakeholderType));
		List<ProjectStakeholder> projectStakeholders = ListUtil.toList(this.projectStakeholderDao.findAll(condition));
		Set<Long> projectIds = new HashSet<Long>();
		for (ProjectStakeholder projectStakeholder : projectStakeholders) {
			projectIds.add(projectStakeholder.getProject().getId());
		}
		if (!projectIds.isEmpty()) {
			condition = new BooleanBuilder();
			condition.and(this.$.projectMilestone.project.id.in(projectIds));
			if (StringUtil.isNotEmpty(status)) {
				condition.and($.status.eq(status));
			}
			return ListUtil.toList(projectMilestoneChangeDao.findAll(condition));
		}
		return null;
	}

	public void checkProjectMilestoneDelay(ProjectMilestoneChange projectMilestoneChange) throws CannotUpdateException {
		ProjectMilestoneChange sourceProjectMilestoneChange = this.projectMilestoneChangeDao.findOne(projectMilestoneChange.getId());
		if(!ProcessStatus.DELAY_APPLY.equals(sourceProjectMilestoneChange.getStatus())){
			throw new CannotUpdateException("项目节点延期发生变化，请刷新后再试！");
		}
		sourceProjectMilestoneChange.setCheckPerson(projectMilestoneChange.getCheckPerson());
		sourceProjectMilestoneChange.setCheckTime(DateUtil.nowDate());
		sourceProjectMilestoneChange.setCheckComment(projectMilestoneChange.getCheckComment());
		sourceProjectMilestoneChange.setStatus(projectMilestoneChange.getStatus());
		
		ProjectMilestone projectMilestone = sourceProjectMilestoneChange.getProjectMilestone();
		if(ProcessStatus.EXAMINE_SUCCESS.equals(projectMilestoneChange.getStatus())){
			projectMilestone.setPlanFinishDate(projectMilestoneChange.getTargetDate());
			projectMilestone.setPlanReviseCount(projectMilestone.getPlanReviseCount() + 1);
		}
		projectMilestone.setStatus(projectMilestoneChange.getProjectMilestone().getStatus());
		
		this.projectMilestoneChangeDao.save(sourceProjectMilestoneChange);
		this.projectMilestoneDao.save(projectMilestone);
	}

	public void revocationChangeApplyProjectMilestoneChangeApply(ProjectMilestoneChange projectMilestoneChange) throws CannotUpdateException {
		ProjectMilestoneChange sourceProjectMilestoneChange = this.projectMilestoneChangeDao.findOne(projectMilestoneChange.getId());
		if(!ProcessStatus.DELAY_APPLY.equals(sourceProjectMilestoneChange.getStatus())){
			throw new CannotUpdateException("项目节点延期发生变化，请刷新后再试！");
		}
		
		sourceProjectMilestoneChange.setStatus(projectMilestoneChange.getStatus());
		sourceProjectMilestoneChange.setAnnulDate(DateUtil.nowDate());
		
		ProjectMilestone projectMilestone = sourceProjectMilestoneChange.getProjectMilestone();
		projectMilestone.setStatus(projectMilestoneChange.getProjectMilestone().getStatus());
		
		this.projectMilestoneChangeDao.save(sourceProjectMilestoneChange);
		this.projectMilestoneDao.save(projectMilestone);
	}

	public ProjectMilestoneChange findOne(Long id) {
		return this.projectMilestoneChangeDao.findOne(id);
	}
	
}
		
